package cn.wsalix.user.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.anlaser.admin.BaseUser;
import cn.anlaser.form.UploadFileForm;
import cn.anlaser.service.impl.BasicServiceImpl;
import cn.anlaser.type.FileTypeEnum;
import cn.anlaser.type.ImageTypeEnum;
import cn.anlaser.utils.BeanMapper;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.admin.entity.SysUser;
import cn.wsalix.admin.form.UserForm;
import cn.wsalix.config.AppConfig;
import cn.wsalix.login.entity.QQUser;
import cn.wsalix.observable.service.AddressChangeService;
import cn.wsalix.observable.service.BuyService;
import cn.wsalix.observable.service.FileUploadService;
import cn.wsalix.observable.service.LoginService;
import cn.wsalix.observable.service.RegisterService;
import cn.wsalix.order.entity.Order;
import cn.wsalix.order.form.OrderForm;
import cn.wsalix.shiro.token.QQToken;
import cn.wsalix.shiro.token.WxAppToken;
import cn.wsalix.type.AuthEnum;
import cn.wsalix.type.GenderEnum;
import cn.wsalix.user.entity.Address;
import cn.wsalix.user.entity.AuthInfo;
import cn.wsalix.user.entity.Authenticate;
import cn.wsalix.user.entity.Contact;
import cn.wsalix.user.entity.UserInfo;
import cn.wsalix.user.form.AddressForm;
import cn.wsalix.user.form.AuthForm;
import cn.wsalix.user.form.ContactForm;
import cn.wsalix.user.form.UserInfoForm;
import cn.wsalix.user.repository.AuthInfoRepository;
import cn.wsalix.user.repository.AuthRepository;
import cn.wsalix.user.repository.ContactRepository;
import cn.wsalix.user.repository.UserInfoRepository;
import cn.wsalix.user.service.UserInfoService;
import cn.wsalix.utils.UserUtils;
import cn.wsalix.weixin.entity.WxUser;

@Service("userInfoService")
public class UserInfoServiceImpl extends
		BasicServiceImpl<UserInfoForm, UserInfoRepository, UserInfo> implements
		UserInfoService {
	@Autowired
	private int pageSize;
	@Autowired
	private UserInfoRepository userInfoRepository;

	@Autowired
	protected UserUtils userUtils;
	@Autowired
	private AppConfig appConfig;

	@Override
	public String module() {
		return "/user/user_info";
	}

	@Override
	public UserInfoRepository getRepository() {
		return userInfoRepository;
	}

	@Transactional
	@Override
	public UserInfo findByUser(SysUser user) {
		UserInfo obj = super.findById(user.getId());
		if (obj == null) {
			obj = initUserInfo(new UserForm(), user);
			userInfoRepository.save(obj);
		}
		if (obj.getPageSize() == 0) {
			obj.setPageSize(pageSize);
		}
		return obj;
	}

	@Override
	public UserInfo findByUser(Long userId) {
		return super.findById(userId);
	}

	@Transactional
	@Override
	public UserInfo edit(UserInfoForm form) {
		UserInfo obj = userInfoRepository.findByUserIdOne(form.getId());
		if (obj == null) {
			// TODO report Error
			return null;
		}
		SysUser user = obj.getUser();
		if (form.getNickname() != null && !form.getNickname().equals("")) {
			obj.setNickname(form.getNickname());
		}
		if (form.getRealname() != null && !form.getRealname().equals("")) {
			obj.setRealname(form.getRealname());
		}
		if (form.getGender() != null && !form.getGender().equals("")) {
			obj.setGender(GenderEnum.findByCode(form.getGender()));
		}
		if (form.getBirthday() != null && !form.getBirthday().equals("")) {
			obj.setBirthday(form.getBirthday());
		}
		if (form.getEmail() != null && !form.getEmail().equals("")) {
			obj.setEmail(form.getEmail());
		}
		if (form.getPhone() != null && !form.getPhone().equals("")) {
			obj.setPhone(form.getPhone());
		}
		return super.edit(obj);
	}

	@Override
	public Class<UserInfo> getEntityClazz() {
		return UserInfo.class;
	}

	@Override
	public Map<String, SearchFilter> buildByForm(UserInfoForm entity) {
		Map<String, Object> searchParams = new HashMap<String, Object>();
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		if (entity.getUserId() != null && entity.getUserId() != 0) {
			filters.put("user.id", new SearchFilter("user.id", Operator.EQ,
					entity.getUserId()));
		}
		return filters;
	}

	@Transactional
	@Override
	public void update(Observable o, Object arg) {
		if (o instanceof FileUploadService) {
			// FileUploadService fileUploadService = (FileUploadService) o;
			/*
			 * if (arg instanceof UploadFile) { UploadFile obj = (UploadFile)
			 * arg;
			 * 
			 * if (obj.getType().getCode().equals("avatar")){// ==
			 * FileTypeEnum.avatar.ordinal()) {// 用户头像 UserInfo user =
			 * userInfoRepository.findOne(obj.getFkId());
			 * user.setAvatar(obj.getHttpUrl()); super.edit(user); } }
			 */
			if (arg instanceof UploadFileForm) {
				UploadFileForm obj = (UploadFileForm) arg;
				if (obj.getType().ordinal() == FileTypeEnum.image.ordinal()) {
					if (obj.getImageType().equals(ImageTypeEnum.avatar.name())) {// 用户头像
						UserInfo user = userInfoRepository.findOne(obj
								.getFkId());
						user.setAvatar(obj.getHttpUrl());
						super.edit(user);
					}
				}
			}
		}
		if (o instanceof RegisterService) {
			if (arg instanceof UserForm) {
				UserForm form = (UserForm) arg;
				SysUser user = form.getUser();
				if (user == null) {
					logger.error("user is null");
					//throw Global
							//.getException("SysUser is null,Please contact the administrator");
				}
				UserInfo userInfo = initUserInfo(form, user);

				userInfoRepository.save(userInfo);
			}

			// SysUser setNickname setRealName 通过userinfo回写
		}
		if (o instanceof AddressChangeService) {
			AddressChangeService addressChangeService = (AddressChangeService) o;
			AddressForm form = (AddressForm) arg;
			Address address = addressChangeService.getAddress();
			// SysUser sysUser = userService.findById(address.getUserId());
			UserInfo obj = userInfoRepository.findByUserIdOne(address
					.getUserId());

			// UserInfo obj =
			// userInfoRepository.findByUserIdOne(address.getCustomer().getId());
			obj.setAddress(address.getAddress());
			obj.setCustomerName(address.getContacts());
			obj.setPhone(address.getPhone());
			edit(obj);
		}
		if (o instanceof LoginService) {
			BaseUser baseUser = userUtils.getUser();
			if (baseUser != null) {// 用户已登录，自动绑定账号
				return;
			}
			LoginService loginService = (LoginService) o;
			SysUser user = loginService.getUser();
			UserInfo obj = userInfoRepository.findByUserIdOne(user.getId());
			if (arg instanceof QQToken) {
				QQToken upToken = (QQToken) arg;
				QQUser qqUser = upToken.getQqUser();
				if (obj == null) {
					obj = BeanMapper.map(qqUser, UserInfo.class);
					obj.setUser(user);
					obj.setAvatar(qqUser.getFigureurl());
					obj.setGender(GenderEnum.unknown);
					userInfoRepository.save(obj);
				} else {
					obj.setCountry(qqUser.getCountry());
					obj.setProvince(qqUser.getProvince());
					obj.setCity(qqUser.getCity());
					userInfoRepository.saveAndFlush(obj);
				}

			}
			if (arg instanceof WxAppToken) {
				// SysUser user = userLoginService.getUser();
				WxAppToken upToken = (WxAppToken) arg;
				WxUser wxUser = upToken.getWxUser();
				// UserInfo obj =
				// userInfoRepository.findByUserIdOne(user.getId());
				if (obj == null) {
					obj = new UserInfo();
					obj.setUser(user);
					obj.setNickname(wxUser.getNickname());
					obj.setAvatar(wxUser.getHeadimgurl());
					obj.setGender(GenderEnum.findByTitle(wxUser.getSex()));// .equals("1")?"男":"女"
					obj.setCountry(wxUser.getCountry());
					obj.setProvince(wxUser.getProvince());
					obj.setCity(wxUser.getCity());
					userInfoRepository.save(obj);
				} else {
					obj.setAvatar(wxUser.getHeadimgurl());
					obj.setNickname(wxUser.getNickname());
					userInfoRepository.saveAndFlush(obj);
				}
			}
			if (user.getUserInfo() == null) {
				loginService.setUserInfo(obj);
			}
		}
		if (o instanceof BuyService) {// 购买时，给订单设置收货地址
			BuyService buyService = (BuyService) o;
			OrderForm orderForm = (OrderForm) arg;
			Order order = buyService.getOrder();
			UserInfo userInfo = userInfoRepository.findByUserIdOne(order
					.getCustomer().getId());
			order.setPhone(userInfo.getPhone());
			order.setAddress(userInfo.getAddress());
			order.setCustomerName(userInfo.getCustomerName());

		}
	}

	private UserInfo initUserInfo(UserForm form, SysUser user) {
		UserInfo userInfo = new UserInfo();

		userInfo.setUser(user);
		userInfo.setRegisterTime(new Date());
		userInfo.setUsername(user.getUsername());
		if (form.getNickname() == null || form.getNickname().equals("")) {
			userInfo.setNickname(user.getUsername());
		} else {
			userInfo.setNickname(form.getNickname());
		}
		if (form.getRealname() == null || form.getRealname().equals("")) {
			userInfo.setRealname(user.getUsername());
		} else {
			userInfo.setRealname(form.getRealname());
		}
		userInfo.setGender(GenderEnum.unknown);
		userInfo.setAvatar(appConfig.getDefualtAvatar());
		return userInfo;
	}

	@Autowired
	protected ContactRepository contactRepository;

	@Transactional
	@Override
	public Contact crtContact(ContactForm form) {
		Contact obj = BeanMapper.map(form, Contact.class);
		// traversalAssign(form, obj);
		return contactRepository.save(obj);
	}

	@Transactional
	@Override
	public Contact editContact(ContactForm form) {
		Contact obj = contactRepository.findOne(form.getId());
		// traversalAssign(form, obj);
		return contactRepository.save(obj);
	}

	@Transactional
	@Override
	public Contact cloneContact(ContactForm form) {
		// TODO Auto-generated method stub
		return null;
	}

	@Autowired
	protected AuthRepository authRepository;

	@Transactional
	@Override
	public Authenticate crtAuth(AuthForm form) {
		Authenticate obj = BeanMapper.map(form, Authenticate.class);
		// traversalAssign(form, obj);
		return authRepository.save(obj);
	}

	@Transactional
	@Override
	public Authenticate passAuth(AuthForm form) {
		Authenticate obj = authRepository.findOne(form.getId());
		obj.setStatus(AuthEnum.pass);
		return authRepository.save(obj);
	}

	@Transactional
	@Override
	public Authenticate unPassAuth(AuthForm form) {
		Authenticate obj = authRepository.findOne(form.getId());
		obj.setStatus(AuthEnum.unPass);
		return authRepository.save(obj);
	}

	@Autowired
	protected AuthInfoRepository authInfoRepository;

	@Transactional
	@Override
	public AuthInfo uploadAuthInfo(AuthForm form) {
		AuthInfo obj = authInfoRepository.findOne(form.getId());
		// traversalAssign(form, obj);
		return authInfoRepository.save(obj);
	}

	@Transactional
	@Override
	public AuthInfo passAuthInfo(AuthForm form) {
		AuthInfo obj = authInfoRepository.findOne(form.getId());
		obj.setStatus(AuthEnum.pass);
		return authInfoRepository.save(obj);
	}

	@Transactional
	@Override
	public AuthInfo unPassAuthInfo(AuthForm form) {
		AuthInfo obj = authInfoRepository.findOne(form.getId());
		obj.setStatus(AuthEnum.unPass);
		return authInfoRepository.save(obj);
	}
}
